<template>
	<div ref="refMyFormItem">
		<!-- label太长设置为tooltip，使用description字段传递 -->
		<DefineLabel v-slot="{ item }">
			<el-tooltip :content="item.description" placement="top">
				<span class="c-p">{{ item.label }}</span>
			</el-tooltip>
		</DefineLabel>

		<!-- FormItem内容模板 -->
		<DefineTemplate v-slot="{ item }">
			<slot :name="item.prop" :model="$attrs.model" :prop="item.prop" :item="item">
				<!-- 详情展示 -->
				<template v-if="detail">
					<component
						v-if="['file', 'img', 'switch', 'select', 'tree', 'cascader'].includes(item.itemType) && !item.detailFn"
						:is="componentObj[item.itemType || 'input']"
						v-model="$attrs.model[item.prop]"
						v-bind="itemFn(item)"
						detail
						disabled
					/>
					<template v-else>{{ item?.detailFn?.(item) || $attrs.model[item.prop] }}</template>
				</template>
				<!-- 编辑 -->
				<template v-else>
					<component
						:is="componentObj[item.itemType || 'input']"
						v-model="$attrs.model[item.prop]"
						v-bind="itemFn(item)"
						v-on:[item.incident]="item[item.incident]"
					>
						<template #append v-if="item.append">
							<component :is="item.append()" v-if="typeof item.append === 'function'" />
							<template v-else>
								{{ item.append }}
							</template>
						</template>
						<template #prefix v-if="item.prefix">
							<component :is="item.prefix()" v-if="typeof item.prefix === 'function'" />
							<template v-else>
								{{ item.prefix }}
							</template>
						</template>
					</component>
				</template>
			</slot>
		</DefineTemplate>

		<!-- 栅格布局 非查询form表单 -->
		<el-row v-bind="$attrs.row || {}" v-if="row && !query">
			<template v-for="item of formItem" :key="item.prop">
				<template v-if="item.if !== false">
					<el-col v-bind="item.col || (colFlag ? { sm: 12, md: 8, lg: 6 } : {})" v-show="item.show !== false">
						<el-form-item :prop="item.prop" :label="detail ? `${item.label}：` : item.label" v-bind="item.formItemprops">
							<template #label>
								<slot :name="item.prop + '_label'" v-bind="item">
									<ReuseLabel v-if="item.description" v-bind="{ item }" />
								</slot>
							</template>
							<ReuseTemplate v-bind="{ item, detail, $attrs }" />
						</el-form-item>
					</el-col>
				</template>
			</template>
		</el-row>

		<!-- 查询form表单自适应布局 非栅格布局-->
		<template v-else>
			<template v-for="(item, index) of formItem" :key="item.prop">
				<template v-if="item.if !== false">
					<el-form-item
						:prop="item.prop"
						:label="detail ? `${item.label}：` : item.label"
						:style="query && { width: itemWidth }"
						v-show="(!query && item.show !== false) || (query && (index < currentColumn || !currentCollapsed))"
						v-bind="item.formItemprops"
					>
						<template #label>
							<slot :name="item.prop + '_label'" v-bind="item">
								<!-- query——label对齐写法 -->
								<template v-if="query">
									<span v-for="i in item.label.length" :key="item.label.charAt(i)">{{ item.label.charAt(i - 1) }}</span>
								</template>
								<ReuseLabel v-if="item.description" v-bind="{ item }" />
							</slot>
						</template>
						<ReuseTemplate v-bind="{ item, detail, $attrs }" />
					</el-form-item>
				</template>
				<!-- 查询form表单默认按钮 -->
				<template
					v-if="
						query &&
						((index === currentColumn - 1 && formItem.length > currentColumn) || (formItem.length <= currentColumn && index === formItem.length - 1))
					"
				>
					<el-form-item style="margin-right: 0 !important">
						<div ref="refMyFormQuery">
							<el-button class="el-button--primary" icon="Search" @click.prevent="searchFn()">搜索</el-button>
							<el-button
								icon="Refresh"
								@click.prevent="
									() => {
										resetForm(refMyForm);
										$attrs.model.orderAndSc = null;
										searchFn(true);
									}
								"
							>
								重置
							</el-button>
							<template v-if="collapsible && formItem.length > currentColumn">
								<el-button class="m-l-20" link type="primary" @click.stop.prevent="currentCollapsed = !currentCollapsed">
									{{ currentCollapsed ? '展开' : '收起' }}
									<el-icon>
										<arrow-down v-show="currentCollapsed" />
										<arrow-up v-show="!currentCollapsed" />
									</el-icon>
								</el-button>
							</template>
						</div>
					</el-form-item>
				</template>
			</template>
		</template>
	</div>
</template>

<script setup name="MyFormItem">
/************************** 动态组件相关 ***************************/
// import MyTreeSelect from '../my-tree-select';
// import MyCascader from '../my-cascader';
// import MySelect from '../my-select';
// import MyInputNumber from '../my-input-number';
// import MyFileUpload from '../my-file-upload';
// import MyDatePicker from '../my-date-picker';
// import MyImgUpload, { MyImgUploadOne } from '../my-img-upload';
// import MyEditor from '../my-editor';
// import MyRadio from '../my-radio';
// import MyCheckbox from '../my-checkbox';
// import MySignature from '../my-signature';
// import MyNative from '../my-native';
// import MyInput from '../my-input';

const componentObj = {
	tree: defineAsyncComponent(() => import('../my-tree-select')),
	cascader: defineAsyncComponent(() => import('../my-cascader')),
	select: defineAsyncComponent(() => import('../my-select')),
	number: defineAsyncComponent(() => import('../my-input-number')),
	date: defineAsyncComponent(() => import('../my-date-picker')),
	file: defineAsyncComponent(() => import('../my-file-upload')),
	img: defineAsyncComponent(() => import('../my-img-upload')),
	imgOne: defineAsyncComponent(() => import('../my-img-upload/my-img-upload-one.vue')),
	editor: defineAsyncComponent(() => import('../my-editor')),
	signature: defineAsyncComponent(() => import('../my-signature')),
	radio: defineAsyncComponent(() => import('../my-radio')),
	checkbox: defineAsyncComponent(() => import('../my-checkbox')),
	native: defineAsyncComponent(() => import('../my-native')),
	input: defineAsyncComponent(() => import('../my-input')),
	switch: defineAsyncComponent(() => import('element-plus').then((mod) => mod['ElSwitch'])),
	autocomplete: defineAsyncComponent(() => import('element-plus').then((mod) => mod['ElAutocomplete'])),
	inputTag: defineAsyncComponent(() => import('element-plus').then((mod) => mod['ElInputTag'])),
	mention: defineAsyncComponent(() => import('element-plus').then((mod) => mod['ElMention'])),
	rate: defineAsyncComponent(() => import('element-plus').then((mod) => mod['ElRate'])),
	slider: defineAsyncComponent(() => import('element-plus').then((mod) => mod['ElSlider']))
};

/************************** 组件内模板 ***************************/
import { createReusableTemplate } from '@vueuse/core';
const [DefineTemplate, ReuseTemplate] = createReusableTemplate();
const [DefineLabel, ReuseLabel] = createReusableTemplate();

/************************** 组件逻辑 ***************************/
import { useElementSize, computedAsync } from '@vueuse/core';

const $attrs = useAttrs(),
	refMyFormItem = shallowRef(null),
	refMyFormQuery = shallowRef(null),
	MyFormWidth = useElementSize(refMyFormItem).width;

/***
 * props
 * @property {Array} formItem 生成form表单的配置数组
 * @property {Boolean} query 是否默认添加查询 重置按钮
 * @property {Boolean} collapsible 是否支持表单项展开、收起 (必须在是query为true的时候才会生效)
 * @property {Boolean} [collapsed=true] 初始收起表单项目，collapsible=true是才有效
 * @property {Boolean} [detail=false] 表单是否为详情展示表单默认为FALSE
 * @property {Boolean} [colFlag=false] 栅格布局 - 是否开启表单响应式布局
 * @property {Document} [refMyForm] form元素dom节点
 * @property {Function} [searchFn] 查询表单，查询函数
 */
const props = defineProps({
		formItem: {
			type: Array,
			required: true
		},
		query: {
			type: Boolean,
			default: false
		},
		collapsible: {
			type: Boolean,
			default: true
		},
		collapsed: {
			type: Boolean,
			default: true
		},
		detail: {
			type: Boolean,
			default: false
		},
		colFlag: {
			type: Boolean,
			default: false
		},
		refMyForm: {},
		searchFn: {
			type: Function
		}
	}),
	// 一行显示的form-item数量
	currentColumn = computed(() => {
		const width = MyFormWidth.value;
		if (width <= 700) {
			return 1;
		} else if (width >= 700 && width <= 1171) {
			return 2;
		} else if (width >= 1172 && width <= 1379) {
			return 3;
		} else if (width >= 1380 && width <= 1779) {
			return 4;
		} else if (width >= 1780) {
			return 5;
		}
	}),
	// form-item宽度
	itemWidth = computedAsync(() => {
		if (refMyFormQuery.value && MyFormWidth.value !== 0) {
			return nextTick(() => {
				const queryWidth = Math.ceil(refMyFormQuery.value?.[0]?.clientWidth) + 1;
				if (queryWidth) return `calc(${100 / currentColumn.value}% - ${10 + queryWidth / currentColumn.value}px) !important`;
			});
		}
	}),
	// 当前的折叠状态
	currentCollapsed = ref(props.collapsed),
	// 是否使用el-row布局进行响应式页面
	row = computed(() => !!$attrs.row || props.formItem?.some?.((item) => !!item.col) || props.colFlag);

// 查询表单时，查询函数必需传递
watch(
	() => props.query,
	(val) => {
		if (val) {
			if (!props.searchFn) throw new Error('query is true，searchFn is required');
		}
	},
	{
		immediate: true
	}
);

// form-item的参数处理逻辑
function itemFn(item) {
	const data = cloneDeep(item);
	if (['tree', 'cascader', 'select', 'date'].includes(data.itemType)) {
		data.placeholder = data.placeholder || `请选择${data.label || ''}`;
	} else {
		data.placeholder = data.placeholder || `请输入${data.label || ''}`;
	}
	delete data.label;
	delete data.prop;
	delete data.itemType;
	delete data.show;
	delete data.col;
	delete data.required;
	return data;
}
</script>

<style lang="scss" scoped>
:deep() {
	// .el-form-item,
	.el-select,
	.el-cascader,
	.el-input-number,
	.el-input__wrapper,
	.el-textarea,
	.el-input {
		box-sizing: border-box;
		width: 100% !important;
	}
}
</style>
